<template>
    <el-form ref="formRef" class="form-wrap" label-width="130" scroll-to-error :model="ruleForm">
        <template v-for="item in fields" :key="item.field_id">
          <el-col :span="(item.col || 1) * 6" v-if="!item.hiddenShow">
            <template v-if="item.isSlot">
              <slot name="mySlot"></slot>
            </template>
            <el-form-item v-else :label="item.label" class="form-item-wrap" :prop="item.field_id"
                          :rules="[{required: item.required,message: item.requiredMsg || (item.label + '不能为空'),trigger: 'blur'}]">
              <m-form-item :field="item" class="item-wrap" v-bind="$attrs" :value="mValue[item.field_id]" @m-change.self="handleChange"/>
            </el-form-item>
          </el-col>
        </template>
    </el-form>
</template>

<script setup>
    import {ref,reactive, defineProps,watch,toRefs} from 'vue'
    import MFormItem from './FormItem'

    /*
    *  属性：
    *  @param {array} fields：字段参数集合
    *  @param {string} field.field_id  提交数据传入的字段id
    *  @param {string} field.show_field 传入值value中该字段对应的字段id
    *  @param {string} field.label 字段名称
    *  @param {string} field.type 字段类型：text文本类型、textarea多行文本、number数字、picklist单选、multiple多选、date日期、datetime日期时间、reference引用、bool逻辑
    *  @param {string} field.format 日期类型显示格式YYYY-MM-DD HH:mm:ss
    *  @param {number} field.precision 数字类型小数位
    *  @param {number} field.col 显示列数1、2、3、4
    *  @param {array} field.options 选择类型字段选项
    *  @param {string} field.refUrl 引用类型字段请求地址，
    *  @param {string} field.refParam 引用类型字段请求参数
    *  @param {string} field.refCols 引用类型字段显示表头
    *  @param {string} field.entityKey 引用类型字段获取表格数据的主显示字段，默认值name
    *  @param {array} field.valueKey 引用类型字段提交值字段，返回引用选择后值的对象所需的字段id集合，如果集合内值为字符串，则提交和表格显示的字段一致，若不一致通过对象获取{key：value} key对应提交数据的字段id，value对应表格显示的字段
    *  @param {array} field.searchField 引用类型字段搜索字段
    *  @param {boolean} field.disabled 禁用
    *  @param {boolean} field.readonly 只读
    *  @param {boolean} field.required 必填
    *  @param {string} field.requiredMsg 必填提示信息，默认‘[label]不能为空’
    *  @param {object} value：字段值对象
    *  @param {Function} bindChange：字段变化回调函数
    * */
    const props = defineProps(['fields','value','bindChange']);

    let rules = ref({
      id: [{required: true, message: 'age is required'}
      ]
    })

    let ruleForm = reactive({}),
      mValue = reactive({}),
      formRef = ref(null);

    /*
    * 监听
    * props.value：属性值value 变化触发内部数据 mValue变化
    * mValue： mValue变化触发事件修改value实现双向绑定
    * */
    watch(() => props.value,(val) =>{
      if (!val)return
      ruleForm = val;

      props.fields.forEach(item => {
        mValue[item.field_id] = val[item.field_id] || '';   //val为{}时，字段值为undefined，子组件中undefined不修改值，因此需赋值''
        //清除验证
        formRef.value && formRef.value.clearValidate(item.field_id)
      })

    },{immediate: true});

    /*watch(() => mValue,(val) => {
      console.log('form-mValue：',val)
      ruleForm = val;
    },{deep: true})*/

    /*let fields = ref([
      {label: '字段一',field_id: 'field1',type: 'text',col: 1},
      {label: '字段二',field_id: 'field2',type: 'text',col: 2},
      {label: '字段三',field_id: 'field3',type: 'text',col: 3},
      {label: '字段四',field_id: 'field4',type: 'text',col: 4},
      {label: '字段五',field_id: 'field5',type: 'reference',col: 4},
      {label: '字段五',field_id: 'field5',type: 'reference',col: 1},
      {label: '字段六',field_id: 'field6',type: 'picklist',col: 4},
      {label: '字段七',field_id: 'field7',type: 'multiple',col: 2},
      {label: '字段八',field_id: 'field8',type: 'datetime',col: 2},
      {label: '字段九',field_id: 'field8',type: 'bool',col: 1},
    ])*/

    //字段变化-修改验证表单对象
    function handleChange(data) {
      for (let key in data){
        ruleForm[key] = data[key];
        mValue[key] = data[key]
      }
      props.bindChange && props.bindChange(mValue)
      // formRef.value.validate();
    }
    //表单验证
    const validate = (callback) =>{
      formRef.value.validate(valid =>{
        callback(valid)
      });
    }

    defineExpose({validate,getData: () => ruleForm})

</script>
<style scoped lang="less">
.form-wrap{
    display: flex;
    flex-wrap: wrap;
    width: 100%;

    /*.form-item-wrap{
        margin-bottom: 10px;
    }*/
    .item-wrap{
        padding-left: 10px;
    }

}
</style>
